package com.cw.jeeyt.common;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Date;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.cw.jeeyt.common.utils.Base64Util;

import cn.hutool.core.codec.Base64;

/**
 * 公共方法类
 *
 * @author chenw
 * @version 1.0.0
 */
@SuppressWarnings("restriction")
@Component
public class CommonUtil {
    /**
     * json类型转换
     *
     * @return
     */
    public static SerializerFeature[] getFeatures() {
        SerializerFeature[] features = {SerializerFeature.WriteNullNumberAsZero,
            SerializerFeature.WriteNullStringAsEmpty, SerializerFeature.DisableCircularReferenceDetect,
            SerializerFeature.WriteMapNullValue};
        return features;
    }

    /**
     * 生成主键 规则-模块名+年月日时分秒+随机数6位 ad20160902101121854163
     *
     * @return
     */
    public static String generateId(String moduleId) {
        Date date = new Date();
        //获取当前时间字符串
        String dateStr = DateTool.formatDate(date, DateTool.PATTERN_DATETIME_COMPACT);
        //获取6位随机数
        Random random = new Random();
        String randomStr = "";
        for (int i = 0; i < 6; i++) {
            randomStr += random.nextInt(10);
        }
        return moduleId + dateStr + randomStr;
    }

    /**
     * 生成随机数字id
     *
     * @return
     */
    public static Integer generateNumberId(int num) {
        //获取8位随机数
        Random random = new Random();
        String randomStr = "";
        for (int i = 0; i < num; i++) {
            randomStr += random.nextInt(10);
        }
        return Integer.parseInt(randomStr);
    }

    /**
     * 利用MD5进行加密
     *
     * @param str 待加密的字符串
     * @return 加密后的字符串
     * @throws NoSuchAlgorithmException 没有这种产生消息摘要的算法
     * @throws UnsupportedEncodingException
     */
    public static String encoderByMd5(String str) throws Exception {
        //确定计算方法
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        //加密后的字符串
        String newstr = Base64.encode(md5.digest(str.getBytes("utf-8")));
        return newstr;
    }

    /**
     * 数据库字段类型转成java类型
     *
     * @param sqlType
     * @return
     */
    public static String sqlType2JavaType(String sqlType) {
        if (sqlType.equalsIgnoreCase("bit")) {
            return "Boolean";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("smallint") || sqlType.equalsIgnoreCase(
            "tinyint")) {
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "Float";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
            || sqlType.equalsIgnoreCase("real")) {
            return "java.math.BigDecimal";
        } else if (sqlType.equalsIgnoreCase("money") || sqlType.equalsIgnoreCase("smallmoney")) {
            return "java.math.BigDecimal";
        } else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase(
            "nvarchar") || sqlType.equalsIgnoreCase("nchar") || sqlType.equalsIgnoreCase("text")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime") || sqlType.equalsIgnoreCase("timestamp")) {
            return "java.util.Date";
        } else if (sqlType.equalsIgnoreCase("image")) {
            return "java.sql.Blob";
        }
        return "String";
    }

    /**
     * mysql数据库字段类型转成oracle字段类型
     *
     * @param sqlType
     * @return
     */
    public static String mysqlType2OracleType(String sqlType) {
        if (sqlType.equalsIgnoreCase("bit")) {
            return "NVARCHAR2";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("smallint") || sqlType.equalsIgnoreCase(
            "tinyint")) {
            return "INTEGER";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "INTEGER";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "NUMBER";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
            || sqlType.equalsIgnoreCase("real")) {
            return "NUMBER";
        } else if (sqlType.equalsIgnoreCase("money") || sqlType.equalsIgnoreCase("smallmoney")) {
            return "NUMBER";
        } else if (sqlType.equalsIgnoreCase("varchar")) {
            return "NVARCHAR2";
        } else if (sqlType.equalsIgnoreCase("char")) {
            return "NVARCHAR2";
        } else if (sqlType.equalsIgnoreCase("datetime") || sqlType.equalsIgnoreCase("timestamp")
            || sqlType.equalsIgnoreCase("date")) {
            return "DATE";
        } else if (sqlType.equalsIgnoreCase("text") || sqlType.equalsIgnoreCase("mediumtext")
            || sqlType.equalsIgnoreCase("longtext") || sqlType.equalsIgnoreCase("tinytext")) {
            return "NCLOB";
        } else if (sqlType.equalsIgnoreCase("longblob")) {
            return "BLOB";
        }
        return "NVARCHAR2";
    }

    /**
     * 数据库类型转成java类型
     *
     * @param sqlType
     * @param scale
     * @return
     */
    public static String sqlType2JavaType(String sqlType, int scale) {
        if (sqlType.equalsIgnoreCase("bit")) {
            return "Boolean";
        } else if (sqlType.equalsIgnoreCase("int") || sqlType.equalsIgnoreCase("smallint") || sqlType.equalsIgnoreCase(
            "tinyint") || (sqlType.equalsIgnoreCase("number") && scale == 0)) {
            return "Integer";
        } else if (sqlType.equalsIgnoreCase("bigint")) {
            return "Long";
        } else if (sqlType.equalsIgnoreCase("float")) {
            return "Float";
        } else if (sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric")
            || sqlType.equalsIgnoreCase("real") || (sqlType.equalsIgnoreCase("number") && scale > 0)) {
            return "Double";
        } else if (sqlType.equalsIgnoreCase("money") || sqlType.equalsIgnoreCase("smallmoney")) {
            return "Double";
        } else if (sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char") || sqlType.equalsIgnoreCase(
            "nvarchar") || sqlType.equalsIgnoreCase("nchar") || sqlType.equalsIgnoreCase("nvarchar2")) {
            return "String";
        } else if (sqlType.equalsIgnoreCase("datetime") || sqlType.equalsIgnoreCase("timestamp")
            || sqlType.equalsIgnoreCase("date")) {
            return "java.util.Date";
        } else if (sqlType.equalsIgnoreCase("image")) {
            return "java.sql.Blob";
        } else if (sqlType.equalsIgnoreCase("text")) {
            return "String";
        }
        return "String";
    }

    /**
     * Convert field name, such as 'user_name' to 'userName'
     *
     * @param columnName
     * @return
     */
    public static String getFieldName(String columnName) {
        if (columnName == null) {
            return null;
        }
        columnName = columnName.toLowerCase();
        String[] names = columnName.split("_");
        StringBuilder filedName = new StringBuilder();
        for (int i = 0; i < names.length; i++) {
            if (names[i].trim()
                .equals("")) {
                continue;
            }
            if (filedName.length() == 0) {
                filedName.append(names[i].trim());
                continue;
            }
            filedName.append(StringUtils.capitalize(names[i].trim()));
        }

        return filedName.toString();
    }

    /**
     * Convert field name, such as 'userName' to 'user_name'
     *
     * @param fieldName
     * @return
     */
    public static String getColumnName(String fieldName) {
        if (fieldName == null) {
            return null;
        }
        StringBuilder columnName = new StringBuilder();
        for (int i = 0; i < fieldName.length(); i++) {
            char ch = fieldName.charAt(i);
            if (Character.isUpperCase(ch) && columnName.length() > 0) {
                columnName.append("_");
            }
            columnName.append(ch);
        }
        return columnName.toString()
            .toLowerCase();
    }

    /**
     * 获取用户真实IP地址，不使用request.getRemoteAddr();的原因是有可能用户使用了代理软件方式避免真实IP地址,
     * 参考文章： http://developer.51cto.com/art/201111/305181.htm
     *
     * 可是，如果通过了多级反向代理的话，X-Forwarded-For的值并不止一个，而是一串IP值，究竟哪个才是真正的用户端的真实IP呢？
     * 答案是取X-Forwarded-For中第一个非unknown的有效IP字符串。
     *
     * 如：X-Forwarded-For：192.168.1.110, 192.168.1.120, 192.168.1.130,
     * 192.168.1.100
     *
     * 用户真实IP为： 192.168.1.110
     *
     * @param request
     * @return
     */
    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    public static void main(String[] args) {
        System.out.println(CommonUtil.getFieldName("t_user_name"));
        System.out.println(CommonUtil.getColumnName("tUserName"));
    }
}
